<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta http-equiv="origin-trial"
          content="Aq/fFdFqA/KG1fJKStAZThEk9ZRHR6TrNS07X5A/NMEG0NMRYemab+FoZVn9wrnL8YwhsCWckbLxUzIUN0MRWgQAAABheyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjYzMzQyIiwiZmVhdHVyZSI6IlVucmVzdHJpY3RlZFNoYXJlZEFycmF5QnVmZmVyIiwiZXhwaXJ5IjoxNzY5NDcyMDAwfQ==">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Jessibuca vr demo</title>
    <script src="./vconsole.js"></script>
    <script src="./js/jessibuca-pro-vr-demo.js"></script>
    <script src="./js/jessibuca-pro-demo.js"></script>
    <link rel="stylesheet" href="./demo.css">
    <style>
        .container-shell:before {
            content: "jessibuca pro vr demo";
        }
    </style>
</head>
<body class="page">
<div class="root">
    <div class="container-shell">
        <div id="container"></div>
        <div class="input">
            <div>
                当前浏览器：
                <span id="mseSupport264" style="color: green;display: none">支持MSE H264解码；</span>
                <span id="mseSupport" style="color: green;display: none">支持MSE H265解码；</span>
                <span id="mseNotSupport264" style="color: red;display: none">不支持MSE H264解码；</span>
                <span id="mseNotSupport"
                      style="color: red;display: none">不支持MSE H265解码,会自动切换成wasm解码；</span>
            </div>
        </div>
        <div class="input">
            <div>
                当前浏览器：
                <span id="wcsSupport264" style="color: green;display: none">支持Webcodecs H264解码；</span>
                <span id="wcsSupport" style="color: green;display: none">支持Webcodecs H265解码（不一定准确）；</span>
                <span id="wcsNotSupport264"
                      style="color: red;display: none">不支持Webcodecs H264解码(https/localhost)；</span>
                <span id="wcsNotSupport" style="color: red;display: none">不支持Webcodecs H265解码(https/localhost),会自动切换成wasm解码</span>
            </div>
        </div>
        <div class="input">
            <div>
                当前浏览器：
                <span id="wasmSupport" style="color: green;display: none">支持WASM解码；</span>
                <span id="simdSupport" style="color: green;display: none">支持WASM SIMD解码；</span>
                <span id="simdMtSupport" style="color: green;display: none">支持WASM WASM(SIMD) 多线程解码；</span>
                <span id="wasmNotSupport" style="color: red;display: none">不支持WASM解码；</span>
                <span id="simdNotSupport"
                      style="color: red;display: none">不支持WASM SIMD解码,会自动切换成wasm解码；</span>
                <span id="simdMtNotSupport" style="color: red;display: none">不支持WASM WASM(SIMD) 多线程解码；</span>
            </div>
        </div>
        <div class="input">
            <div>
                <div>
                    <span>硬解码：</span>
                    <input
                        type="checkbox"
                        id="useMSE"
                    /><span>MediaSource</span>
                    <input
                        type="checkbox"
                        id="useWCS"
                    /><span>Webcodec</span> |
                    <input
                        checked
                        onchange="replay()"
                        type="checkbox"
                        id="audioDecodeUseHardware"
                    />
                    <span>硬解码音频</span>
                </div>
                <div>
                    <span>软解码：</span>
                    <input
                        checked
                        type="checkbox"
                        id="useWASM"
                    /><span>WASM</span>
                    <input
                        type="checkbox"
                        id="useSIMD"
                    /><span>WASM(SIMD)</span>
                    <input
                        type="checkbox" ,
                        id="isFFmpegSIMD"
                        onclick="replay()"
                    /><span>isSIMD(V2)</span>
                    <input
                        type="checkbox"
                        id="useSIMDMThreading"
                        onclick="replay()"
                    /><span>启动多线程（WASM,WASM(SIMD)解码支持）</span>
                    <span style="color: green">默认使用wasm解码器</span>
                </div>
            </div>
        </div>
        <div class="input">
            <span>渲染标签：</span>
            <select id="renderDom" onchange="replay()">
                <option value="video" selected>video</option>
                <option value="canvas">canvas</option>
            </select>

            <span>canvas渲染技术：</span>
            <select id="isUseWebGPU" onchange="replay()">
                <option value="webgl" selected>webgl</option>
                <option value="webgpu">webgpu</option>
                <option value="canvas">canvas</option>
            </select>
            <span id="supportWebgpu"></span>
        </div>
        <div class="input">
            <div>
                <span>缓存时长：</span>
                <input placeholder="单位：秒" type="text" id="videoBuffer" style="width: 50px" value="0.2">秒
                <span>缓存延迟(延迟超过会触发丢帧)：</span>
                <input placeholder="单位：秒" type="text" id="videoBufferDelay" style="width: 50px" value="1">秒
                <button id="replay">重播</button>
            </div>
        </div>
        <div class="input">
            <div>
                <input
                    checked
                    onclick="replay()"
                    type="checkbox"
                    id="demuxUseWorker"
                /><span>硬解码(MediaSource，Webcodec)worker解封装</span>
                <input
                    checked
                    onclick="replay()"
                    type="checkbox"
                    id="mseDecoderUseWorker"
                /><span>硬解码(MediaSource)worker解码</span>
            </div>
        </div>
        <div class="input">
            <div>
                <input
                    checked
                    onclick="replay()"
                    type="checkbox"
                    id="replayUseLastFrameShow"
                /><span>暂停->播放的时候是否使用最后一帧显示</span>
                <input
                    onclick="replay()"
                    type="checkbox"
                    id="replayShowLoadingIcon"
                /><span>暂停->播放的时候是否显示loading效果</span>
            </div>
        </div>
        <div class="input">
            <div>
                <input
                    checked
                    onclick="replay()"
                    type="checkbox"
                    id="controlAutoHide"
                /><span>自动隐藏控制条</span>
            </div>
        </div>

        <div class="input">
            <div>输入URL：</div>
            <input
                autocomplete="on"
                id="playUrl"
                value=""
            />
            <button id="play">播放</button>
            <button id="pause" style="display: none">停止</button>
        </div>
        <div class="input">
            <div>
                <button id="enterVr" onclick="enterVr()">进入vr模式</button>
                <button id="exitVr" onclick="exitVr()">退出vr模式</button>
                <span>初始化方向:Yaw(°)</span><input type="number" style="width: 50px" value="0" id="initYaw"><span>Pitch(°):</span><input
                type="number" style="width: 50px" value="0" id="initPitch">
            </div>
        </div>
        <div class="input">
            <button onclick="enableSensor()">申请运动传感器权限(iOS 13+)</button>
            <button onclick="setGyroMode('VR')">打开陀螺仪</button>
            <button onclick="setGyroMode('none')">关闭陀螺仪</button>
        </div>
        <div class="input">
            <button onclick="lookAt({yaw: 0, pitch: 0})">前方(0°,0°)</button>
            <button onclick="lookAt({yaw: 180, pitch: 0})">后方(180°,0°)</button>
            <button onclick="lookAt({yaw: 90, pitch: 0})">左方(90°,0°)</button>
            <button onclick="lookAt({yaw: -90, pitch: 0})">右方(-90°,0°)</button>
            <button onclick="lookAt({yaw: 0, pitch: 90})">上方(0°,90°)</button>
            <button onclick="lookAt({yaw: 0, pitch: -90})">下方(0°,-90°)</button>
        </div>
        <div class="input" style="line-height: 30px">
            <button onclick="play2()">强制重播</button>
            <button onclick="play()">播放(相同url)</button>
            <button onclick="play3()">播放(不带url)</button>
            <button onclick="pause()">暂停</button>
            <button id="destroy">销毁(重建)</button>
            <button onclick="destroy()" id="destroy2">销毁</button>
            <span class="fps-inner"></span>
        </div>
    </div>
</div>

<script src="./demo.js"></script>
<script>
    var $player = document.getElementById('play');
    var $pause = document.getElementById('pause');
    var $playHref = document.getElementById('playUrl');
    var $container = document.getElementById('container');
    var $destroy = document.getElementById('destroy');
    var $destroy2 = document.getElementById('destroy2');
    var $fps = document.querySelector('.fps-inner');
    var $useMSE = document.getElementById('useMSE');
    var $useSIMD = document.getElementById('useSIMD');
    var $audioDecodeUseHardware = document.getElementById('audioDecodeUseHardware');
    var $useWASM = document.getElementById('useWASM');
    var $isFFmpegSIMD = document.getElementById('isFFmpegSIMD');
    var $useWCS = document.getElementById('useWCS');
    var $videoBuffer = document.getElementById('videoBuffer');
    var $videoBufferDelay = document.getElementById('videoBufferDelay');
    var $replay = document.getElementById('replay');
    var $renderDom = document.getElementById('renderDom');
    var $isUseWebGPU = document.getElementById('isUseWebGPU');
    var $demuxUseWorker = document.getElementById('demuxUseWorker');
    var $useSIMDMThreading = document.getElementById('useSIMDMThreading');
    var $replayUseLastFrameShow = document.getElementById('replayUseLastFrameShow');
    var $replayShowLoadingIcon = document.getElementById('replayShowLoadingIcon');
    var $mseDecoderUseWorker = document.getElementById('mseDecoderUseWorker');
    var $controlAutoHide = document.getElementById('controlAutoHide');
    var $initYaw = document.getElementById('initYaw');
    var $initPitch = document.getElementById('initPitch');
    var showOperateBtns = true; // 是否显示按钮
    var forceNoOffscreen = true; //
    var jessibuca = null;

    function create(options) {
        options = options || {}

        jessibuca = new JessibucaPro({
            container: $container,
            videoBuffer: Number($videoBuffer.value), // 缓存时长
            videoBufferDelay: Number($videoBufferDelay.value), // 1000s
            decoder: './js/decoder-pro.js',
            isResize: false,
            text: "",
            loadingText: "加载中",
            debug: true,
            debugLevel: "debug",
            useMSE: $useMSE.checked === true,
            mseDecodeAudio: $audioDecodeUseHardware.checked === true,
            wcsDecodeAudio: $audioDecodeUseHardware.checked === true,
            decoderErrorAutoWasm: false,
            useSIMD: $useSIMD.checked === true,
            isFFmpegSIMD: $isFFmpegSIMD.checked === true,
            useWCS: $useWCS.checked === true,
            useMThreading: $useSIMDMThreading.checked === true,
            showBandwidth: showOperateBtns, // 显示网速
            showPerformance: showOperateBtns, // 显示性能
            operateBtns: {
                fullscreen: showOperateBtns,
                screenshot: showOperateBtns,
                play: showOperateBtns,
                audio: showOperateBtns,
                performance: showOperateBtns,
            },
            // timeout: 10000,

            // audioEngine: "worklet",
            qualityConfig: ['普清', '高清', '超清', '4K', '8K'],
            forceNoOffscreen: forceNoOffscreen,
            isNotMute: false,
            // heartTimeout: 100000,
            ptzClickType: 'mouseDownAndUp',
            ptzZoomShow: true,
            ptzMoreArrowShow: true,
            ptzApertureShow: true,
            ptzFocusShow: true,
            useCanvasRender: $renderDom.value === 'canvas',
            useWebGPU: $isUseWebGPU.value === 'webgpu',
            useWebCanvas: $isUseWebGPU.value === 'canvas',
            demuxUseWorker: $demuxUseWorker.checked === true,
            controlHtml: '<div>我是 <span style="color: red">test</span>文案</div>',
            audioEngine: "active",
            // isFlv: true
            pauseAndNextPlayUseLastFrameShow: $replayUseLastFrameShow.checked === true,
            heartTimeoutReplayUseLastFrameShow: $replayUseLastFrameShow.checked === true,
            replayUseLastFrameShow: $replayUseLastFrameShow.checked === true, // 重播使用上一帧显示
            replayShowLoadingIcon: $replayShowLoadingIcon.checked === true,// 重播显示loading
            mseDecoderUseWorker: $mseDecoderUseWorker.checked === true,
            controlAutoHide: $controlAutoHide.checked === true,
            // syncAudioAndVideo: false,
            supportHls265: true,
            // mainThreadFetchUseWorker:false,
            // hasAudio:false,
            isEmitSEI: true,
            correctionConfigurationProfileIndication: true,
            correctionConfigurationVersion: true,
            // hls264UseOldDemuxer:true,
            // supportHls265:false,
            // isHls:true
        },);

        jessibuca.on('kBps', (kbps) => {
            // console.log('kbps', kbps);
            console.log('speed', jessibuca.kbps2Speed(kbps));
        })

        jessibuca.on('stats', (stats) => {
            // console.log('stats', stats);
            $fps.textContent = `FPS: ${stats.fps} DFPS: ${stats.dfps}`
        })

        // jessibuca.on('videoSEISyncPts', (value) => {
        //     const decoder = new TextDecoder(); // 创建一个 TextDecoder 对象
        //     // let str = decoder.decode(value.originData);
        //     // let str;
        //
        //     console.log(`videoSEISyncPts pts is ${value.pts} ,ts is ${value.ts},type is ${value.type} size is ${value.size} data is`, value.originData, value.data,'uuid',value.uuid);
        // })

        jessibuca.on('playFailedAndPaused', (error) => {
            console.log('playFailedAndPausedAndPaused',error);
        })

        jessibuca.on(JessibucaPro.EVENTS.crashLog, (log) => {
            console.error('crashLog', log)
        })

        $player.style.display = 'inline-block';
        $pause.style.display = 'none';
        // $destroy2.style.display = 'none';
        $fps.textContent = '';
    }


    create();

    function play() {
        var href = $playHref.value;
        if (href) {
            jessibuca.play(href).then(() => {
                console.log('play success')
                $player.style.display = 'none';
                $pause.style.display = 'inline-block';
                notifySuccess('播放成功');
            }).catch((error) => {
                notifyError(`play error: ${error}`)
                console.error('play error', error)
                jessibuca.showErrorMessageTips(error.toString());
            });
        } else {
            jessibuca.showErrorMessageTips('播放地址不能为空');
        }
    }

    function play2() {
        var href = $playHref.value;
        if (href) {
            jessibuca.play(href, {
                replay: true
            }).then(() => {
                console.log('play success')
                $player.style.display = 'none';
                $pause.style.display = 'inline-block';
                notifySuccess('播放成功');
            }).catch((error) => {
                notifyError(`play error: ${error}`)
                console.error('play error', error)
                jessibuca.showErrorMessageTips(error.toString());
            });

        } else {
            jessibuca.showErrorMessageTips('播放地址不能为空');
        }
    }


    function play3() {
        if (jessibuca) {
            jessibuca.play().then(() => {
                console.log('play success')
                notifySuccess('播放成功');
            }).catch((error) => {
                notifyError(`play error: ${error}`)
                console.error('play error', error)
                jessibuca.showErrorMessageTips(error.toString());
            });
        } else {
            jessibuca.showErrorMessageTips('请先创建播放器');
        }
    }

    function pause() {
        if (jessibuca) {
            jessibuca.pause();
        } else {
            jessibuca.showErrorMessageTips('请先创建播放器');
        }
    }

    function replay(options) {
        if (jessibuca) {
            jessibuca.destroy().then(() => {
                create(options);
                play();
            });
        } else {
            create();
            play();
        }
    }

    $replay.addEventListener('click', function () {
        replay();
    })

    $player.addEventListener('click', function () {
        play();
    }, false)


    $pause.addEventListener('click', function () {
        $player.style.display = 'inline-block';
        $pause.style.display = 'none';
        $fps.textContent = '';
        jessibuca.pause();
    })

    $destroy.addEventListener('click', function () {
        if (jessibuca) {
            jessibuca.destroy().then(() => {
                create();
            });
        } else {
            create();
        }

    })

    function destroy() {
        if (jessibuca) {
            jessibuca.destroy().then(() => {
                console.log('destroy', jessibuca);
            });
        }
    }


    $useMSE.addEventListener('click', function () {
        const checked = $useMSE.checked;
        if (checked) {
            $useSIMD.checked = false
            $useWCS.checked = false
            $useWASM.checked = false
        }
        replay();
    })

    $useSIMD.addEventListener('click', function () {
        const checked = $useSIMD.checked;
        if (checked) {
            $useMSE.checked = false
            $useWCS.checked = false
            $useWASM.checked = false

        }
        replay();
    })

    $useWCS.addEventListener('click', function () {
        const checked = $useWCS.checked;
        if (checked) {
            $useMSE.checked = false
            $useSIMD.checked = false
            $useWASM.checked = false
        }
        replay();
    })

    $useWASM.addEventListener('click', function () {
        const checked = $useWASM.checked;
        if (checked) {
            $useMSE.checked = false
            $useSIMD.checked = false
            $useWCS.checked = false
        }
        replay();
    })

    function enterVr() {
        if (jessibuca) {
            jessibuca.enterVr({
                initYaw: parseFloat($initYaw.value) || 0,
                initPitch: parseFloat($initPitch.value) || 0,
            }).then(() => {
                notifySuccess('进入VR');

            }).catch((error) => {
                notifyError('进入VR失败:' + error.toString());
            });
        }
    }

    function exitVr() {
        if (jessibuca) {
            jessibuca.exitVr().then(() => {
                notifySuccess('退出VR');

            }).catch((error) => {
                notifyError('退出VR失败:' + error.toString());
            });
        }
    }

    function enableSensor() {
        if (jessibuca) {
            jessibuca.vrEnableSensor().then(() => {
                console.log('enableSensor success');
                notifySuccess('申请运动传感器权限成功');
            }).catch((error) => {
                notifyError('申请运动传感器权限失败:' + error.toString());
            })
        }
    }

    function setGyroMode(type) {
        if (jessibuca) {
            jessibuca.vrSetGyroMode(type).then(() => {
                notifySuccess('设置陀螺仪模式成功');
            }).catch((error) => {
                notifyError('设置陀螺仪模式失败:' + error.toString());
            })
        }
    }

    function lookAt(target,duration){
        if(jessibuca) {
            jessibuca.vrLookAt(target,duration);
        }
    }

</script>

</body>
</html>
